﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GameLib.Utils;
using GameLib.Framework;
using System.Collections.ObjectModel;

namespace GameLib.WorldMap
{
	public class River : IContentHost
	{
		public float Width
		{
			get;
			set;
		}

		public bool IsInitialized
		{
			get;
			private set;
		}

		public MapVertex Head
		{
			get { return m_Points.Count > 0 ? m_Points[0] : new MapVertex(); }
		}

		public MapVertex Tail
		{
			get { return m_Points.Count > 0 ? m_Points[m_Points.Count - 1] : new MapVertex(); }
		}

		public List<MapVertex> Points
		{
			get { return m_Points; }
		}

		public void Extend(IEnumerable<MapVertex> points)
		{
			if (!IsInitialized)
				throw new Exception("River must be initialized before extending");

			bool isAddingToTail = true;
			int addedCount = 0;

			if (m_Points.Count > 0)
			{			
				foreach (MapVertex point in points)
				{
					if (!point.IsNeighbour(Tail))
					{
						if (point.IsNeighbour(Head))
							isAddingToTail = false;
						else
							return;
					}
					break;

				}
			}

			foreach (MapVertex point in points)
			{
				if (!point.IsWithinMapBounds(m_Map))
					break;

				if (isAddingToTail)
					m_Points.Add(point);
				else
					m_Points.Insert(0, point);
				addedCount++;
			}
	
			// send a event
			if (addedCount > 0)
			{
				NotifyTilesAlongSide(isAddingToTail ? Math.Max(0, m_Points.Count - addedCount - 1) : 0,
					Math.Min(addedCount + 1, m_Points.Count));

				if (Extended != null)
				{
					RiverExtendedEventArgs evtArgs = new RiverExtendedEventArgs();
					evtArgs.IsExtendingTail = isAddingToTail;
					evtArgs.ExtensionLength = addedCount;
					Extended(this, evtArgs);
				}
			}
		}

		public void Initialize(Map map)
		{
			m_Map = map;
			IsInitialized = true;
			NotifyTilesAlongSide(0, m_Points.Count);
		}

		public event EventHandler<RiverExtendedEventArgs> Extended;

		private void NotifyTilesAlongSide(int start, int count)
		{
			for (int i = start; i < start + count - 1; i++)
			{
				MapEdge edge = new MapEdge((MapVertex)m_Points[i], (MapVertex)m_Points[i + 1]);

				MapEdgeDirection dir = edge.Direction;

				if (!dir.IsValid)
					continue;

				Tile tileA = m_Map.GetTile(edge.TileA);
				if (tileA != null)
					tileA.OnRiverAdded(this, dir);

				Tile tileB = m_Map.GetTile(edge.TileB);

				if (tileB != null)
					tileB.OnRiverAdded(this, dir.Opposite);
				
			}
		}

		private List<MapVertex> m_Points = new List<MapVertex>();
		private Map m_Map;
		private ContentDictionary m_Content = new ContentDictionary();


		#region IContentHost Members

		public ContentDictionary Content
		{
			get { return m_Content; }
		}

		#endregion
	}

	public class RiverExtendedEventArgs : EventArgs
	{
		public bool IsExtendingTail { get; set; }
		public int ExtensionLength { get; set; }
	}
}
